/*
 
    Copyright (c) 2010 Ralf Westphal <info@ralfw.de>
     
    This file is part of NZMQ, nzmq.codeplex.com
     
    NZMQ is free software; you can redistribute it and/or modify it under
    the terms of the Lesser GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
     
    NZMQ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    Lesser GNU General Public License for more details.
     
    You should have received a copy of the Lesser GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.

*/
using System;
using System.Collections.Generic;
using System.Linq;

namespace nzmq
{
    public class NzmqCoordination
    {
        public static bool WaitAll(int timeoutMilliseconds, params NzmqBaseSocket[] sockets)
        {
            return WaitAll(timeoutMilliseconds, sockets.Select(sck => sck.RawSocket.Handle).ToArray());
        }

        public static bool WaitAll(int timeoutMilliseconds, params IntPtr[] socketHandles)
        {
            if (socketHandles.Length == 0) return false;

            libzmq.zmq_pollitem_t[] items = Setup_POLLIN_items(socketHandles);

            var n = libzmq.zmq_poll(items, items.Length, timeoutMilliseconds * 1000);
            if (n < 0) throw new NzmqException();

            return n == socketHandles.Length;
        }


        public static int[] WaitAny(int timeoutMilliseconds, params NzmqBaseSocket[] sockets)
        {
            return WaitAny(timeoutMilliseconds, sockets.Select(sck => sck.RawSocket.Handle).ToArray());
        }

        public static int[] WaitAny(int timeoutMilliseconds, params IntPtr[] socketHandles)
        {
            if (socketHandles.Length == 0) return new int[]{};

            libzmq.zmq_pollitem_t[] items = Setup_POLLIN_items(socketHandles);

            var n = libzmq.zmq_poll(items, items.Length, timeoutMilliseconds * 1000);
            if (n < 0) throw new NzmqException();

            var itemsWithPendingMessages = new List<int>();
            for (var i = 0; i < socketHandles.Length; i++)
                if (items[i].revents == libzmq.POLLIN) itemsWithPendingMessages.Add(i);
            return itemsWithPendingMessages.ToArray();
        }


        private static libzmq.zmq_pollitem_t[] Setup_POLLIN_items(IntPtr[] socketHandles)
        {
            var items = new libzmq.zmq_pollitem_t[socketHandles.Length];
            for (var i = 0; i < socketHandles.Length; i++)
            {
                items[i].socket = socketHandles[i];
                items[i].events = libzmq.POLLIN;
                items[i].revents = 0;
            }
            return items;
        }
    }
}